perf: Migrate to Flashlist in MoneyRequestReportTransactionList#91422
perf: Migrate to Flashlist in MoneyRequestReportTransactionList#91422TMisiukiewicz wants to merge 94 commits into
Conversation
|
@aimane-chnaif Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6b5c9bef51
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
@mountiny can you run another adhoc build here? @aimane-chnaif I think I resolved the remaining bugs, could you check again? |
|
🚧 mountiny has triggered a test Expensify/App build. You can view the workflow run here. |
This comment has been minimized.
This comment has been minimized.
…rt-list # Conflicts: # src/components/MoneyRequestReportView/MoneyRequestReportActionsList.tsx
Regression reviewI reviewed the diff focusing on (a) blast radius outside the money-request report view and (b) behavioral regressions in the migrated list. Three likely regressions, all inside 🔴 Confirmed regressions1. Wide-table horizontal scroll position is no longer restored 2. New/sent-message autoscroll still uses estimated 3. Cold-open deep-link to a report action may not anchor Bot-flagged concerns I checked and refuted (no change needed)
Shared-component & deleted-file changes — no regression outside the report view
Confirmed with code evidence; #1 and #2 are straightforward to reproduce on a large report. Reply with |
Blockers
The PR added Repro: Receive the message coming from another account/device (not current user). New concerns introduced by the
|
Sometimes this doesn't work. Not consistent. Screen.Recording.2026-07-10.at.10.08.24.AM.mov |
not valid - ScrollView does not re-position unless it's re-mounted
fixed in 71f12e8
fixed in 1814a1ee60a8a7ecee5693e468b43eee14713484 |
fixed in 970d609
fixed in 335748a
fixed in 335748a
Nothing in the codebase ever writes a transactionID into that param. I don't think we should write code for a flow that does not exist
not valid
I don't think we have any bug introduced by lack of extraData so I am not in favor of adding this unless necessary
React Compiler handles this
not valid I'll check the resize and send message bugs soon |
|
@aimane-chnaif I can't reproduce the resize bug - can you verify again? Might be accidentally fixed by one of my recent commits 😅 |
|
🚧 mountiny has triggered a test Expensify/App build. You can view the workflow run here. |
|
also couldn't reproduce the issue with the scroll after msg |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|



Explanation of Change
Problem
On heavy money-request reports the RHP list was effectively non-virtualised. The inner transactions section was rendered via plain
.map()inside the parent FlatList'sListHeaderComponent, which renders eagerly. Every transaction row mounted synchronously when the report opened, pushing report open time to ~20–30s for a report with 1600 expenses and producing a noticeable jank window on every navigation.Solution
Unified list — merged the inner transactions section and the outer report-actions section into a single virtualised list. A discriminated-union
UnifiedListItem(section-header|transaction|transactions-footer|report-action) flows through onerenderItemdispatcher, so transactions and chat messages now share the same recycler window instead of one being eagerly rendered inside the other's header.FlashList — migrated the list from
react-native'sFlatList(FlatListWithScrollKey).initialScrollIndexreplaces the FlatList-specificuseFlatListScrollKeywrapperController + sub-component —
MoneyRequestReportTransactionListcontinues to own the transaction-domain state (sort, group-by, selection, columns, totals, etc.) and exposes it to the parent via a render-prop controller. The parent renders a smallMoneyRequestReportUnifiedListsub-component that assembles the FlashList from controller data plus the report-actions listFixed Issues
$ #91425
PROPOSAL:
Tests
Before testing:
npm run i-standaloneas this PR contains patch to the FlashListOffline tests
N/A
QA Steps
Same as tests
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
ios.mov
iOS: mWeb Safari
MacOS: Chrome / Safari
web.mov